/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-05-24                  the first version
 */
#include <stdint.h>
#include <rthw.h>
#include <rtthread.h>
#include "drv_uart.h"
#include "bsp_system.h"
#include "app_sys_param.h"

#define GD32F4_DENSITY          (0x1FFF7A20)

#if defined(PKG_USING_YMODEM_OTA) || defined(PKG_USING_HTTP_OTA)

	#if defined (A5302_EDITION)
    	#define BOOT_FLASH_SIZE                                     	(0xE000)    /* 56k = 56 *1024 = 0xE000*/
	#else 
		#define BOOT_FLASH_SIZE											(0x8000)		/* 32k = 32 *1024*/
	#endif
#else
#define BOOT_FLASH_SIZE										(0x0)
#endif

#define VECTTAB_FLASH_START									NVIC_VECTTAB_FLASH
#define VECTTAB_RAM_START									NVIC_VECTTAB_RAM

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define GD32F450_SRAM_SIZE              				 	(192)
#define GD32F470_SRAM_SIZE                        			(704)
#define GD32F4XX_SRAM_START              					(VECTTAB_RAM_START)
#define GD32F450_SRAM_END                					(GD32F4XX_SRAM_START + GD32F450_SRAM_SIZE * 1024 - 1)
#define GD32F470_SRAM_END                         			(GD32F4XX_SRAM_START + GD32F470_SRAM_SIZE * 1024 - 1)

#define GD32F4XX_TCM_SRAM_SIZE              				(64)

#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
extern int Image$$RW_IRAM2$$ZI$$Limit;
#define SYS_HEAP_BEGIN                          			((void *)&Image$$RW_IRAM1$$ZI$$Limit)  
#define TCM_HEAP_BEGIN                          			((void *)&Image$$RW_IRAM2$$ZI$$Limit)  
#define TCM_SRAM_SIZE              				            (GD32F4XX_TCM_SRAM_SIZE * 1024)
#elif defined(__GNUC__)
extern int __bss_end__;
#define HEAP_BEGIN      			   						((void *)&__bss_end__)
#endif
#define GD32F450_HEAP_END                     		  GD32F450_SRAM_END
#define GD32F470_HEAP_END                           GD32F470_SRAM_END
#endif

#ifdef RT_USING_MEMHEAP_AS_HEAP 
static struct rt_memheap tcm_sdram;
#endif

// Holds the system core clock, which is the system clock 
// frequency supplied to the SysTick timer and the processor 
// core clock.
extern uint32_t SystemCoreClock;

static void bsp_system_init(void)
{
	/* Set the Vector Table base location at GD32F450VE_APP_START_ADDR */
	nvic_vector_table_set(VECTTAB_FLASH_START,	BOOT_FLASH_SIZE);
	
	/* System Clock Update */
	SystemCoreClockUpdate();

	/* System Tick Configuration */
	systick_config(SystemCoreClock / RT_TICK_PER_SECOND);
}

/**
 * This function will initial your board.
 */
void rt_hw_board_init()
{
	rt_uint16_t density = *(rt_uint16_t *)(GD32F4_DENSITY);
	
	bsp_system_init();

	hw_uart_init();
    
#if defined(RT_USING_SERIAL) && defined(RT_USING_FINSH)	
	/* set finsh uart*/
	rt_console_set_device(DEBUG_UART_NAME);
#endif /* RT_USING_SERIAL &&  RT_USING_FINSH*/
	
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
	if (density < GD32F470_SRAM_SIZE) {
        rt_system_heap_init((void *)SYS_HEAP_BEGIN, (void *)GD32F450_HEAP_END);
    } else {
        rt_system_heap_init((void *)SYS_HEAP_BEGIN, (void *)GD32F470_HEAP_END);
    }  
#ifdef RT_USING_MEMHEAP_AS_HEAP
    rt_memheap_init(&tcm_sdram, "tcmram", TCM_HEAP_BEGIN, TCM_SRAM_SIZE);
#endif /* RT_USING_MEMHEAP_AS_HEAP */   
#endif /* RT_USING_HEAP */
     
	rt_kprintf("\r\n");
	rt_kprintf("APC1001C Version: %s build %s\r\n", APP_SW_VERSION, __DATE__);	
	/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
	rt_components_board_init();
#endif

}

void rt_hw_us_delay(rt_uint32_t us)
{
    rt_uint32_t ticks;
    rt_uint32_t told, tnow, tcnt = 0;
    rt_uint32_t reload = SysTick->LOAD;

    /* »ñµÃÑÓÊ±¾­¹ýµÄ tick Êý */
    ticks = us * reload / (1000000 / RT_TICK_PER_SECOND);
    /* »ñµÃµ±Ç°Ê±¼ä */
    told = SysTick->VAL;
    while (1) {
        /* Ñ­»·»ñµÃµ±Ç°Ê±¼ä£¬Ö±µ½´ïµ½Ö¸¶¨µÄÊ±¼äºóÍË³öÑ­»· */
        tnow = SysTick->VAL;
        if (tnow != told) {
            if (tnow < told) {
                tcnt += told - tnow;
            } else {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks) {
                break;
            }
        }
    }
}

